<?php
/**
 *      [Discuz!] (C)2001-2099 Comsenz Inc.
 *      This is NOT a freeware, use is subject to license terms
 *
 *      $Id: mapi_model_article.php 338 2013-04-27 08:06:38Z laoguozhang $
 */

if(!defined('IN_DISCUZ')) {
	exit('Access Denied');
}

/**
 * 通用的CURL功能
 */
class dzf_lib_curl extends dzf_base_model {

	public function __construct() {
		parent::__construct();
	}
	
	/**
	 * 远程curl获取或上报
	 * @param string $url 请求的URL
	 * @param int $limit 返回内容长度限制
	 * @param string $post POST提交的内容
	 * @param string $cookie
	 * @param bool $bysocket 
	 * @param string $ip IP地址
	 * @param int $timeout 超时值
	 * @param bool $block
	 * @param string $encodetype URLENCODE
	 * @param bool $allowcurl
	 * @param int $position
	 * @param string $headers
	 * @return string
	 */
	public function exec($url, $limit = 0, $post = '', $cookie = '', $bysocket = FALSE, $ip = '', $timeout = 15, $block = TRUE, $encodetype  = 'URLENCODE', $allowcurl = TRUE, $position = 0, $headers = null) {
		$return = '';
		$matches = parse_url($url);
		$scheme = $matches['scheme'];
		$host = $matches['host'];
		$path = $matches['path'] ? $matches['path'].($matches['query'] ? '?'.$matches['query'] : '') : '/';
		$port = !empty($matches['port']) ? $matches['port'] : 80;

		if(function_exists('curl_init') && function_exists('curl_exec') && $allowcurl) {
			$ch = curl_init();
			if($ip) {
				$headers = array_merge(array("Host: ".$host), (array)$headers);
			}
			if($headers) {
				curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
			}
			curl_setopt($ch, CURLOPT_URL, $scheme.'://'.($ip ? $ip : $host).($matches['scheme'] != 'https' ? ':'.$port : '').$path);
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	//		curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, TRUE);
	//		curl_setopt($ch, CURLOPT_PROXY, 'proxy.tencent.com:8080');
			curl_setopt($ch, CURLOPT_REFERER, $scheme.'://'.($ip ? $ip : $host));
			if($post) {
				curl_setopt($ch, CURLOPT_POST, 1);
				if($encodetype == 'URLENCODE') {
					curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
				} else {
					parse_str($post, $postarray);
					curl_setopt($ch, CURLOPT_POSTFIELDS, $postarray);
				}
			}
			if($scheme == 'https') {
				curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
				curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
			}
			if($cookie) {
				curl_setopt($ch, CURLOPT_COOKIE, $cookie);
			}
			curl_setopt($ch, CURLOPT_USERAGENT, $_GET['curlUserAgent'] ?: 'Mozilla/5.0 (Linux; U; Android 4.0.3; zh-cn; HTC Sensation Build/IML74K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30');
			curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
			curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
			curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
			curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
			$data = curl_exec($ch);
			$status = curl_getinfo($ch);
			$errno = curl_errno($ch);
			curl_close($ch);
			if($errno || $status['http_code'] != 200) {
				DZF::lib('log')->dlog(14, json_encode(array('errno' => $errno, 'status' => $status)));
				return;
			} else {
				return !$limit ? $data : substr($data, 0, $limit);
			}
		}

		if($post) {
			$out = "POST $path HTTP/1.0\r\n";
			$header = "Accept: */*\r\n";
			$header .= "Accept-Language: zh-cn\r\n";
			$boundary = $encodetype == 'URLENCODE' ? '' : '; boundary='.trim(substr(trim($post), 2, strpos(trim($post), "\n") - 2));
			$header .= $encodetype == 'URLENCODE' ? "Content-Type: application/x-www-form-urlencoded\r\n" : "Content-Type: multipart/form-data$boundary\r\n";
			$header .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n";
			$header .= "Host: $host:$port\r\n";
			$header .= 'Content-Length: '.strlen($post)."\r\n";
			$header .= "Connection: Close\r\n";
			$header .= "Cache-Control: no-cache\r\n";
			$header .= "Cookie: $cookie\r\n\r\n";
			$out .= $header.$post;
		} else {
			$out = "GET $path HTTP/1.0\r\n";
			$header = "Accept: */*\r\n";
			$header .= "Accept-Language: zh-cn\r\n";
			$header .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n";
			$header .= "Host: $host:$port\r\n";
			$header .= "Connection: Close\r\n";
			$header .= "Cookie: $cookie\r\n\r\n";
			$out .= $header;
		}

		$fpflag = 0;
		if(!$fp = @fsocketopen(($ip ? $ip : $host), $port, $errno, $errstr, $timeout)) {
			//note php5支持 开启allow_url_fopen
			$context = array(
				'http' => array(
					'method' => $post ? 'POST' : 'GET',
					'header' => $header,
					'content' => $post,
					'timeout' => $timeout,//note php5.2.1增加此参数
				),
			);
			$context = stream_context_create($context);
			$fp = @fopen($scheme.'://'.($ip ? $ip : $host).':'.$port.$path, 'b', false, $context);//note 不返回header头
			$fpflag = 1;
		}

		if(!$fp) {
			return '';//note $errstr : $errno \r\n
		} else {
			stream_set_blocking($fp, $block);
			stream_set_timeout($fp, $timeout);
			@fwrite($fp, $out);
			$status = stream_get_meta_data($fp);
			if(!$status['timed_out']) {
				while (!feof($fp) && !$fpflag) {
					if(($header = @fgets($fp)) && ($header == "\r\n" ||  $header == "\n")) {
						break;
					}
				}

				if($position) {
					for($i=0; $i<$position; $i++) {
						$char = fgetc($fp);
						if($char == "\n" && $oldchar != "\r") {
							$i++;
						}
						$oldchar = $char;
					}
					//fseek($fp, $position, SEEK_CUR);
				}

				/*
				$stop = false;
				while(!feof($fp) && !$stop) {
					$data = fread($fp, ($limit == 0 || $limit > 8192 ? 8192 : $limit));
					$return .= $data;
					if($limit) {
						$limit -= strlen($data);
						$stop = $limit <= 0;
					}
				}*/
				if($limit) {
					$return = stream_get_contents($fp, $limit);
				} else {
					$return = stream_get_contents($fp);
				}
			}
			@fclose($fp);
			return $return;
		}
	}
}
